using System;

namespace Magiq.Behaviors
{
    public abstract class BehaviorBasedExecution<TBehavior> : BehaviorBasedExecution where TBehavior : IMagiqBehavior
    {
        protected BehaviorBasedExecution(IMagiqBehavior behavior) : base(behavior)
        {
        }

        protected void Call(Action<TBehavior> action)
        {
            Call<TBehavior>(action);
        }

        protected TReturn Call<TReturn>(Func<TBehavior, TReturn> action)
        {
            return Call<TBehavior, TReturn>(action);
        }
    }

    public abstract class BehaviorBasedExecution : MagiqBehavior, IErrorBehavior, IBehaviorBasedExecution
    {
        private IMagiqBehavior behaviorChain;

        protected BehaviorBasedExecution(IMagiqBehavior behavior)
        {
            Behavior = behavior;    
        }

        protected void Call<TBehavior>(Action<TBehavior> action) where TBehavior : IMagiqBehavior
        {
            Execute(behaviorChain, action);
        }

        protected TReturn Call<TBehavior, TReturn>(Func<TBehavior, TReturn> action) where TBehavior : IMagiqBehavior
        {
            return Execute(behaviorChain, action);
        }

        void IErrorBehavior.OnException(Exception exception)
        {
            throw exception;
        }

        public IMagiqBehavior Behavior
        {
            private set
            {
                var behavior = value;

                while (behavior.NextBehavior != null)
                    behavior = behavior.NextBehavior;

                behavior.NextBehavior = this;

                behaviorChain = behavior;
            }
            get { return behaviorChain; }
        }
    }
}